using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace AesEverywhere
{
	public class AES256
	{
		public const int BlockSize = 16;

		public const int KeyLen = 32;

		public const int IvLen = 16;

		private byte[] key;

		private byte[] iv;

		public string Encrypt(string text, string passphrase)
		{
			using RNGCryptoServiceProvider rNGCryptoServiceProvider = new RNGCryptoServiceProvider();
			byte[] array = new byte[8];
			rNGCryptoServiceProvider.GetBytes(array);
			DeriveKeyAndIv(passphrase, array);
			byte[] b;
			using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
			{
				rijndaelManaged.BlockSize = 128;
				rijndaelManaged.Mode = CipherMode.CBC;
				rijndaelManaged.Padding = PaddingMode.PKCS7;
				rijndaelManaged.Key = key;
				rijndaelManaged.IV = iv;
				ICryptoTransform transform = rijndaelManaged.CreateEncryptor(rijndaelManaged.Key, rijndaelManaged.IV);
				using MemoryStream memoryStream = new MemoryStream();
				using CryptoStream stream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write);
				using (StreamWriter streamWriter = new StreamWriter(stream))
				{
					streamWriter.Write(text);
				}
				b = memoryStream.ToArray();
			}
			return Convert.ToBase64String(Concat(Concat("Salted__", array), b));
		}

		public string Decrypt(string encrypted, string passphrase)
		{
			byte[] array = Convert.FromBase64String(encrypted);
			if (array == null || array.Length == 0)
			{
				return "";
			}
			byte[] array2 = new byte[8];
			Array.Copy(array, 0, array2, 0, 8);
			if (Encoding.UTF8.GetString(array2) != "Salted__")
			{
				return "";
			}
			byte[] array3 = new byte[8];
			Array.Copy(array, 8, array3, 0, 8);
			byte[] array4 = new byte[array.Length - 16];
			Array.Copy(array, 16, array4, 0, array.Length - 16);
			DeriveKeyAndIv(passphrase, array3);
			using RijndaelManaged rijndaelManaged = new RijndaelManaged();
			rijndaelManaged.BlockSize = 128;
			rijndaelManaged.Mode = CipherMode.CBC;
			rijndaelManaged.Padding = PaddingMode.PKCS7;
			rijndaelManaged.Key = key;
			rijndaelManaged.IV = iv;
			ICryptoTransform transform = rijndaelManaged.CreateDecryptor(rijndaelManaged.Key, rijndaelManaged.IV);
			using MemoryStream stream = new MemoryStream(array4);
			using CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read);
			using StreamReader streamReader = new StreamReader(stream2);
			return streamReader.ReadToEnd();
		}

		protected void DeriveKeyAndIv(string passphrase, byte[] salt)
		{
			MD5 mD = MD5.Create();
			key = new byte[32];
			iv = new byte[16];
			byte[] array = new byte[0];
			byte[] array2 = new byte[0];
			byte[] bytes = Encoding.UTF8.GetBytes(passphrase);
			for (int i = 0; i < 33; i++)
			{
				array = Concat(Concat(array, bytes), salt);
				array = mD.ComputeHash(array);
				array2 = Concat(array2, array);
			}
			Array.Copy(array2, 0, key, 0, 32);
			Array.Copy(array2, 32, iv, 0, 16);
		}

		private static byte[] Concat(byte[] a, byte[] b)
		{
			byte[] array = new byte[a.Length + b.Length];
			for (int i = 0; i < a.Length; i++)
			{
				array[i] = a[i];
			}
			for (int j = 0; j < b.Length; j++)
			{
				array[a.Length + j] = b[j];
			}
			return array;
		}

		private static byte[] Concat(string a, byte[] b)
		{
			return Concat(Encoding.UTF8.GetBytes(a), b);
		}
	}
}
